This chapter will look at the Windows 95 API or Application Programming Interface. The Windows 95 API consists of a large number of functions that Microsoft has made available for you to use. Usually, an API function does something that is part of the
operating system. For example, determining the display resolution or finding out how much memory is available.
Visual Basic wraps the Windows 95 API into an easy-to-program environment. When you display a command button, Visual Basic translates your requests into function calls to the API. Normally, you don't need to worry about what the API consists of.
Sometimes, however, Visual Basic does not allow you to use a specific operating system function call. When this happens, you need to call the API yourself. This chapter will show you how to do this.
API functions are located inside DLL files. A DLL, short for Dynamic Link Library, is a collection of functions located in a single file. Windows 95 knows how to find a specific function inside a DLL file. The Visual Basic Declare statement links the
statement name with the DLL file and tells Visual Basic what parameters an API function needs and what type of data it returns, if any.
This chapter is not an exhaustive listing of the over 1,300 available Windows 95 API functions; instead, it will show you how some functions can be used in real-life situations. Table 22.1 lists the API functions mentioned in this chapter and the
listing number in which the function is used. A copy of each listing has been included on the CD-ROM provided with this book.
API Function |
Code Listing (Page Number) |
Short Description |
CloseHandle |
Listing 22.6, p. 646 |
This function terminates a thread or process. |
CreateFontIndirect |
Listing 22.8, p. 651 |
This function creates a logical font that can be selected as the current font for any device. |
CreateProcessA |
Listing 22.6, p. 646 |
This function executes a given file starting a new process and thread. It is important to close both the thread and the process using the CloseHandle function. |
DeleteObject |
Listing 22.8, p. 651 |
This function frees all memory associated with an object. An object can be a font, pen, palette, and so on. |
GetCurrentDirectory |
Listing 22.3, p. 641 |
This function returns the current directory. |
GetPrivateProfileInt |
Listing 22.5, p. 643 |
This function returns an integer value from a private INI file. |
GetPrivateProfileString |
Listing 22.5, p. 643 |
This function returns a value from a private INI file. |
GetProfileInt |
Listing 22.5, p. 643 |
This function returns an integer value from the WIN.INI file. |
GetProfileString |
Listing 22.5, p. 643 |
This function returns a value from the WIN.INI file. |
GetSystemDirectory |
Listing 22.3, p. 641 |
The function returns the system subdirectory under the main Windows directory. The system directory contains such files as DLLs, drivers, and font files. |
GetSystemMetrics |
Listing 22.2, p. 639 |
This function returns the height and width of various Windows elements and the values of various system configuration values. |
GetTempPath |
Listing 22.3, p. 641 |
This function returns the directory Windows uses as temporary storage. |
GetVersionEx |
Listing 22.1, p. 638 |
This function returns information about the version number of Windows. |
GetWindowsDirectory |
Listing 22.3, p. 641 |
This function returns the directory in which Windows was installed. |
GetWindowRect |
Listing 22.4, p. 642 |
This function returns the corner coordinates of a given object. |
hread |
Listing 22.12, p. 659 |
This function reads blocks (can be > 64K) of data from files. |
hwrite |
Listing 22.12, p. 659 |
This function writes blocks (can be > 64K) of data to files. |
lclose |
Listing 22.12, p. 659 |
This function closes files. |
LZClose |
Listing 22.6, p. 646 |
This function closes files opened with the LZOpenFile function. |
LZCopy |
Listing 22.6, p. 646 |
This function copies a file opened with LZOpenFile. |
LZOpenFile |
Listing 22.6, p. 646 |
This function opens a file that might be compressed. |
LZRead |
Listing 22.6, p. 646 |
This function reads from a compressed file as if it were not compressed. |
LZSeek |
Listing 22.6, p. 646 |
This function positions the file pointer in a compressed file as if the file were not compressed. |
OpenFile |
Listing 22.12, p. 659 |
This function creates, opens, or deletes a file. |
ReleaseCapture |
Listing 22.11, p. 657 |
This function releases the mouse capture for the current thread and restores normal mouse input processing. |
SelectObject |
Listing 22.8, p. 651 |
This function selects an object for use in a given device context. |
SetCapture |
Listing 22.11, p. 657 |
This function allows the current thread to capture all mouse events. |
SetCursorPos |
Listing 22.4, p. 642 |
This function sets the mouse pointer position. |
TextOut |
Listing 22.8, p. 651 |
This function displays text using a given device context. |
WaitForSingleObject |
Listing 22.6, p. 646 |
This function waits for a process, thread, or object to get into a desired state. |
WritePrivateProfileString |
Listing 22.5, p. 643 |
This function writes an application/key value profile string to a private INI file. |
WriteProfileString |
Listing 22.5, p. 643 |
This function writes an application/key value profile string to the WIN.INI file. |
As you look at the examples in this chapter and explore the rest of the API, remember that some API functions are very dangerous. (For example, the menu API functions clash with Visual Basic.) Save your work often! If you have trouble, look at the
following list for ideas:
Most of the changes to API are because of the need to support 32-bit operations. Many functions have been added to support the new functionality of the Windows 95 operating system. Additional OLE functionality has also been added. Following is a short
list of changes that affect how API calls are made:
The following sections are devoted to short topics that allow you to interact with the Windows operation system.
Sometimes, it is nice to know the version of Windows your program is running in. The recommended method for doing this is to use the GetVersionEx API function. Listing 22.1 shows how to call the function. The main difference between GetVersionEx and the
older GetVersion function is that the major and minor version numbers are split into separate structure members.
The GetVersionEx function also lets you determine which type of Windows platform your program is running on: Win32s, Windows, or Windows NT. Listing 22.1 shows you how to check for each platform type.
Option Explicit Private Type OSVERSIONINFO dwOSVersionInfoSize As Long dwMajorVersion As Long dwMinorVersion As Long dwBuildNumber As Long dwPlatformId As Long szCSDVersion As String * 128 End Type ' dwPlatformId defines: Private Const VER_PLATFORM_WIN32s = 0 Private Const VER_PLATFORM_WIN32_WINDOWS = 1 Private Const VER_PLATFORM_WIN32_NT = 2 Private Declare Function GetVersionEx Lib "kernel32" _ Alias "GetVersionExA" _ (lpVersionInformation As OSVERSIONINFO) As Long Private Sub Form_Load() Dim v As OSVERSIONINFO v.dwOSVersionInfoSize = Len(v) GetVersionEx v MsgBox "Major Version = " & v.dwMajorVersion MsgBox "Minor Version = " & v.dwMinorVersion MsgBox "Build Number = " & v.dwBuildNumber If v.dwPlatformId = VER_PLATFORM_WIN32s Then MsgBox "Win32s" If v.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS Then MsgBox "Windows" If v.dwPlatformId = VER_PLATFORM_WIN32_NT Then MsgBox "Windows NT" End Sub
Several API functions allow you to access information about the Windows system your program is running on. The program in Listing 22.2 prints out all the information available from the GetSystemMetrics function. There are 45 different pieces of
information you can access using this one function.
Private Const SM_CXSCREEN = 0 Private Const SM_CYSCREEN = 1 Private Const SM_CXVSCROLL = 2 Private Const SM_CYHSCROLL = 3 Private Const SM_CYCAPTION = 4 Private Const SM_CXBORDER = 5 Private Const SM_CYBORDER = 6 Private Const SM_CXDLGFRAME = 7 Private Const SM_CYDLGFRAME = 8 Private Const SM_CYVTHUMB = 9 Private Const SM_CXHTHUMB = 10 Private Const SM_CXICON = 11 Private Const SM_CYICON = 12 Private Const SM_CXCURSOR = 13 Private Const SM_CYCURSOR = 14 Private Const SM_CYMENU = 15 Private Const SM_CXFULLSCREEN = 16 Private Const SM_CYFULLSCREEN = 17 Private Const SM_CYKANJIWINDOW = 18 Private Const SM_MOUSEPRESENT = 19 Private Const SM_CYVSCROLL = 20 Private Const SM_CXHSCROLL = 21 Private Const SM_DEBUG = 22 Private Const SM_SWAPBUTTON = 23 Private Const SM_RESERVED1 = 24 Private Const SM_RESERVED2 = 25 Private Const SM_RESERVED3 = 26 Private Const SM_RESERVED4 = 27 Private Const SM_CXMIN = 28 Private Const SM_CYMIN = 29 Private Const SM_CXSIZE = 30 Private Const SM_CYSIZE = 31 Private Const SM_CXFRAME = 32 Private Const SM_CYFRAME = 33 Private Const SM_CXMINTRACK = 34 Private Const SM_CYMINTRACK = 35 Private Const SM_CXDOUBLECLK = 36 Private Const SM_CYDOUBLECLK = 37 Private Const SM_CXICONSPACING = 38 Private Const SM_CYICONSPACING = 39 Private Const SM_MENUDROPALIGNMENT = 40 Private Const SM_PENWINDOWS = 41 Private Const SM_DBCSENABLED = 42 Private Const SM_CMOUSEBUTTONS = 43 Private Const SM_CMETRICS = 44 Private Declare Function GetSystemMetrics Lib "user32" _ (ByVal nIndex As Long) As Long Private Sub logMetric(nIndex As Long, name As String, desc As String) Dim ret As Long ret = GetSystemMetrics(nIndex) Printer.Print name; " = "; ret; Tab(30); "' "; desc End Sub Private Sub Form_Load() logMetric SM_CXSCREEN, "SM_CXSCREEN", "Screen width in pixels" logMetric SM_CYSCREEN, "SM_CYSCREEN", "Screen height in pixels" logMetric SM_CXVSCROLL, "SM_CXVSCROLL", "Vertical scroll arrow width" logMetric SM_CYHSCROLL, "SM_CYHSCROLL", "Horizontal scroll arrow height" logMetric SM_CYCAPTION, "SM_CYCAPTION", "Caption bar height" logMetric SM_CXBORDER, "SM_CXBORDER", "Window border width" logMetric SM_CYBORDER, "SM_CYBORDER", "Window border height" logMetric SM_CXDLGFRAME, "SM_CXDLGFRAME", "Dialog window frame width" logMetric SM_CYDLGFRAME, "SM_CYDLGFRAME", "Dialog window frame height" logMetric SM_CYVTHUMB, "SM_CYVTHUMB", "Vertical scroll thumb height" logMetric SM_CXHTHUMB, "SM_CXHTHUMB", "Horizontal scroll thumb width" logMetric SM_CXICON, "SM_CXICON", "Icon width" logMetric SM_CYICON, "SM_CYICON", "Icon height" logMetric SM_CXCURSOR, "SM_CXCURSOR", "Cursor width" logMetric SM_CYCURSOR, "SM_CYCURSOR", "Cursor height" logMetric SM_CYMENU, "SM_CYMENU", "Menu bar height" logMetric SM_CXFULLSCREEN, "SM_CXFULLSCREEN", "Full screen client area width" logMetric SM_CYFULLSCREEN, "SM_CYFULLSCREEN", "Full screen client area height" logMetric SM_CYKANJIWINDOW, "SM_CYKANJIWINDOW", "Kanji window height" logMetric SM_MOUSEPRESENT, "SM_MOUSEPRESENT", "Mouse present flag" logMetric SM_CYVSCROLL, "SM_CYVSCROLL", "Vertical scroll arrow height" logMetric SM_CXHSCROLL, "SM_CXHSCROLL", "Horizontal scroll arrow width" logMetric SM_DEBUG, "SM_DEBUG", "Debug version flag" logMetric SM_SWAPBUTTON, "SM_SWAPBUTTON", "Mouse buttons swapped flag" logMetric SM_RESERVED1, "SM_RESERVED1", "Reserved" logMetric SM_RESERVED2, "SM_RESERVED2", "Reserved" logMetric SM_RESERVED3, "SM_RESERVED3", "Reserved" logMetric SM_RESERVED4, "SM_RESERVED4", "Reserved" logMetric SM_CXMIN, "SM_CXMIN", "Minimum window width" logMetric SM_CYMIN, "SM_CYMIN", "Minimum window height" logMetric SM_CXSIZE, "SM_CXSIZE", "Minimize/Maximize icon width" logMetric SM_CYSIZE, "SM_CYSIZE", "Minimize/Maximize icon height" logMetric SM_CXFRAME, "SM_CXFRAME", "Window frame width" logMetric SM_CYFRAME, "SM_CYFRAME", "Window frame height" logMetric SM_CXMINTRACK, "SM_CXMINTRACK", "Minimum window tracking width" logMetric SM_CYMINTRACK, "SM_CYMINTRACK", "Minimum window tracking height" logMetric SM_CXDOUBLECLK, "SM_CXDOUBLECLK", "Double click x tolerance (3.1)" logMetric SM_CYDOUBLECLK, "SM_CYDOUBLECLK", "Double click y tolerance (3.1)" logMetric SM_CXICONSPACING, "SM_CXICONSPACING", "Horizontal icon spacing (3.1)" logMetric SM_CYICONSPACING, "SM_CYICONSPACING", "Vertical icon spacing (3.1)" logMetric SM_MENUDROPALIGNMENT, "SM_MENUDROPALIGNMENT", "Left or right menu drop (3.1)" logMetric SM_PENWINDOWS, "SM_PENWINDOWS", "Pen extensions installed (3.1)" logMetric SM_DBCSENABLED, "SM_DBCSENABLED", "DBCS version of USER32 installed" logMetric SM_CMOUSEBUTTONS, "SM_CMOUSEBUTTONS", "Number of buttons on mouse" logMetric SM_CMETRICS, "SM_CMETRICS", "SM_CMETRICS" Printer.NewPage Printer.EndDoc End Sub
Using the GetSystemMetrics function is simple. All the action in Listing 22.2 occurs in the logMetric subroutine. This subroutine calls the GetSystemMetrics function and then prints the result to the Printer object. For more information about the
Printer object, see Chapter 12, "Printing with Visual Basic."
You can also use the API to locate information about what directories Windows is using. For example, the GetWindowsDirectory API function lets you know the directory in which Windows was installed. Listing 22.3 shows how to use the four API functions
that get information about the directories Windows is using.
Private Declare Function GetCurrentDirectory Lib "kernel32" _ Alias "GetCurrentDirectoryA" (ByVal nBufferLength As Long, _ ByVal lpBuffer As String) As Long Private Declare Function GetSystemDirectory Lib "kernel32" _ Alias "GetSystemDirectoryA" (ByVal lpBuffer As String, _ ByVal nSize As Long) As Long Private Declare Function GetTempPath Lib "kernel32" _ Alias "GetTempPathA" (ByVal nBufferLength As Long, _ ByVal lpBuffer As String) As Long Private Declare Function GetWindowsDirectory Lib "kernel32" _ Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, _ ByVal nSize As Long) As Long Private Sub Form_Load() Dim curDir As String Dim sysDir As String Dim tmpDir As String Dim winDir As String curDir = Space(500) sysDir = Space(500) tmpDir = Space(500) winDir = Space(500) curDir = Left(curDir, GetCurrentDirectory(Len(curDir), curDir)) sysDir = Left(sysDir, GetSystemDirectory(sysDir, Len(sysDir))) tmpDir = Left(tmpDir, GetTempPath(Len(tmpDir), tmpDir)) winDir = Left(winDir, GetWindowsDirectory(winDir, Len(winDir))) MsgBox curDir MsgBox sysDir MsgBox tmpDir MsgBox winDir End Sub
Occasionally, you find a feature in a program's user interface that you want to duplicate. This happened to me a little while ago: Every time a dialog box popped up, the mouse pointer was located on the most likely command button—a nifty feature.
Although the WINAPI.TXT file (in the beta version of Visual Basic) does not have an entry for the SetCursorPos API function, the code in Listing 22.4 uses Windows 3.1 as a base to show how you can declare the SetCursorPos function.
To run the program in Listing 22.4, create a form with two command buttons. Then copy the code from the CD-ROM. After starting the program, click the first command button. The cursor should automatically move to the second command button.
Private Type POINTAPI x As Long y As Long End Type Private Type RECT left As Long top As Long Right As Long Bottom As Long End Type Private Declare Function SetCursorPos Lib "user32" _ (ByVal x As Long, ByVal y As Long) As Long Private Declare Function GetWindowRect Lib "user32" _ (ByVal hwnd As Long, lpRect As RECT) As Long Dim p As POINTAPI Dim r As RECT Dim rWidth As Long, rHeight As Long Private Sub Command1_Click() GetWindowRect Command2.hwnd, r rWidth = r.Right - r.left rHeight = r.Bottom - r.top SetCursorPos r.left + (rWidth / 2), r.top + (rHeight / 2) End Sub
The GetWindowRect function is called to get the screen coordinates of the corners of the second command button. The coordinates of the center of the button are then found and SetCursorPos is called.
Windows 3.1 used initialization (INI) files to hold information used when Windows and other applications were started. INI files contained information such as the default printer, starting directories, and the last bookmark viewed in a file. In short,
whatever information the program wanted to remember from one invocation to the next was stored in the INI file.
Microsoft no longer recommends the use of INI files because Windows 95—and Windows NT—use a System Registry to store initialization information. However, you still need to know about INI files to interact with Windows 3.1 programs and,
perhaps, to read information from the WIN.INI file.
Although there are ten API functions that deal with INI files, this section discusses only six of them (three that work with the WIN.INI file and three that work with private or application INI files). Each of the functions is used in Listing 22.5 to
show you how to interact with them.
The format of an INI file looks like this:
[VB Unleashed] ' <== Section Name Chapter Number = 22-Using the Windows 95 API. ' <== Key Name & value ... [next section] ' <== Section Name ...
Each INI file is a series of section names and key names with their values.
Option Explicit Private Declare Function GetProfileInt Lib "kernel32" _ Alias "GetProfileIntA" (ByVal lpAppName As String, _ ByVal lpKeyName As String, ByVal nDefault As Long) As Long Private Declare Function GetProfileString Lib "kernel32" _ Alias "GetProfileStringA" (ByVal lpAppName As String, _ ByVal lpKeyName As String, ByVal lpDefault As String, _ ByVal lpReturnedString As String, ByVal nSize As Long) As Long Private Declare Function WriteProfileString Lib "kernel32" _ Alias "WriteProfileStringA" (ByVal lpszSection As String, _ ByVal lpszKeyName As String, ByVal lpszString As String) As Long Private Declare Function GetPrivateProfileInt Lib "kernel32" _ Alias "GetPrivateProfileIntA" (ByVal lpApplicationName As String, _ ByVal lpKeyName As String, ByVal nDefault As Long, _ ByVal lpFileName As String) As Long Private Declare Function GetPrivateProfileString Lib "kernel32" _ Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, _ ByVal lpKeyName As String, ByVal lpDefault As String, _ ByVal lpReturnedString As String, ByVal nSize As Long, _ ByVal lpFileName As String) As Long Private Declare Function WritePrivateProfileString Lib "kernel32" _ Alias "WritePrivateProfileStringA" _ (ByVal lpApplicationName As String, ByVal lpKeyName As String, _ ByVal lpString As String, ByVal lpFileName As String) As Long Dim secName As String Dim keyName As String Dim prvName As String Private Sub Form_Load() Dim keyValue As String secName = "VB Unleashed" keyName = "Chapter Number" prvName = "sams.ini" keyValue = "22-Using the Windows 95 APIs" testProfile WriteProfileString secName, keyName, keyValue testProfile WriteProfileString secName, keyName, "" testProfile testPrivateProfile WritePrivateProfileString secName, keyName, keyValue, prvName testPrivateProfile WritePrivateProfileString secName, keyName, "", prvName testPrivateProfile End Sub Private Sub testProfile() Dim lChapNum As Long Dim sChapNum As String lChapNum = GetProfileInt(secName, keyName, 10) sChapNum = Space(50) GetProfileString secName, keyName, "10", sChapNum, Len(sChapNum) MsgBox "Chapter Int = " & lChapNum MsgBox "Chapter Str = " & sChapNum End Sub Private Sub testPrivateProfile() Dim lChapNum As Long Dim sChapNum As String lChapNum = GetPrivateProfileInt(secName, keyName, 10, prvName) sChapNum = Space(50) GetPrivateProfileString secName, keyName, "10", sChapNum, Len(sChapNum), prvName MsgBox "Private Chapter Int = " & lChapNum MsgBox "Private Chapter Str = " & sChapNum End Sub
You can see that the functions for the WIN32API.TXT file and the private files parallel each other. The program in Listing 22.5 first calls the testProfile function. The testProfile function looks for a section called VB
Unleashed and then for the key name Chapter Number in WIN.INI. These won't be found; therefore the default value of 10 is returned and displayed in a message box.
Next, the WriteProfileString function is called to create the section name, key name, and key values in the WIN.INI file. The testProfile function is called again to verify that the entries were correctly created.
Then the WriteProfileString function is called to delete the entries just added. And the testProfile function is called to verify that the entries were deleted.
The code performs the same operations using a private INI file called SAMS.INI. If the SAMS.INI file does not exist, the WritePrivateProfileString function creates it.
This section has not discussed the GetProfileSection, WriteProfileSection, GetPrivateProfileSection, or WritePrivateProfileSection API functions. However, if you want to explore their use, you will find the constant vbNullChar to be invaluable. To read
or set an entire section of an INI file, the API function needs a series of NULL-terminated strings, with the last string terminated by two NULLs. You can append the vbNullChar constant directly to a string to represent the NULL character.
One of the more intriguing sets of API functions are located in the LZ32 DLL file. This file contains the Windows decompression API functions. You can use these functions to decompress files that were compressed using the COMPRESS executable. All files
whose extensions end in an underscore (for example, FIGHT.IN_) have been compressed. Usually, files are compressed to save room on a diskette; the files are expanded during application installation.
However, the LZ32 DLL library also contains two functions (lzseek and lzread) that allow you to manipulate a compressed file as if it were normal size. This means that you can use a compressed file to hold inventory parts and still use normal routines
to extract the data. Unfortunately, the API function only lets you read from the compressed file. To create, modify, or insert information, you first must expand the file, then make the change and recompress the file.
Still, the ability to use compressed databases, even in a read-only fashion, is valuable. In addition, the compression can act as a rudimentary encryption. It is possible that only another programmer will catch on to the idea that the file has been
compressed instead of encrypted.
Listing 22.6 shows the class definition of COMPRESSION. It has routines to compress, expand, and read a file. If you are entering the code by hand, set the class module Name to "Compression" and set its Public flag to TRUE.
Option Explicit Private Const OF_READ = &H0 Private Const OF_CREATE = &H1000 Private Const OFS_MAXPATHNAME = 128 Private Const NORMAL_PRIORITY_CLASS = &H20& Private Const INFINITE = -1& ' OpenFile() Structure Private Type OFSTRUCT cBytes As Byte fFixedDisk As Byte nErrCode As Integer Reserved1 As Integer Reserved2 As Integer szPathName(OFS_MAXPATHNAME) As Byte End Type Private Type STARTUPINFO cb As Long lpReserved As String lpDesktop As String lpTitle As String dwX As Long dwY As Long dwXSize As Long dwYSize As Long dwXCountChars As Long dwYCountChars As Long dwFillAttribute As Long dwFlags As Long wShowWindow As Integer cbReserved2 As Integer lpReserved2 As Long hStdInput As Long hStdOutput As Long hStdError As Long End Type Private Type PROCESS_INFORMATION hProcess As Long hThread As Long dwProcessID As Long dwThreadID As Long End Type Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _ hHandle As Long, ByVal dwMilliseconds As Long) As Long Private Declare Function CreateProcessA Lib "kernel32" (ByVal _ lpApplicationName As Long, ByVal lpCommandLine As String, ByVal _ lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _ ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _ ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, _ lpStartupInfo As STARTUPINFO, lpProcessInformation As _ PROCESS_INFORMATION) As Long Private Declare Function CloseHandle Lib "kernel32" (ByVal _ hObject As Long) As Long Private Declare Function LZCopy Lib "lz32.dll" (ByVal _ hfSource As Long, ByVal hfDest As Long) As Long Private Declare Function LZOpenFile Lib "lz32.dll" Alias "LZOpenFileA" _ (ByVal lpszFile As String, lpOf As OFSTRUCT, ByVal style As Long) _ As Long Private Declare Function LZSeek Lib "lz32.dll" (ByVal _ hfFile As Long, ByVal lOffset As Long, ByVal nOrigin _ As Long) As Long Private Declare Function LZRead Lib "lz32.dll" (ByVal _ hfFile As Long, ByVal lpvBuf As String, ByVal cbread _ As Long) As Long Private Declare Sub LZClose Lib "lz32.dll" (ByVal hfFile As Long) Private expandedName As String Private compressedName As String Property Get fileName() As String fileName = expandedName End Property Property Let fileName(fName As String) expandedName = fName End Property Public Sub compress() Dim p As PROCESS_INFORMATION Dim s As STARTUPINFO Dim procStatus As Long ' Initialize the STARTUPINFO structure: s.cb = Len(s) ' Start the shelled application: ' make sure that close upon exit is checked. CreateProcessA 0&, "setupkit\compress -r " & expandedName, _ 0&, 0&, 1&, _ NORMAL_PRIORITY_CLASS, 0&, 0&, s, p ' Wait for the shelled application to finish: WaitForSingleObject p.hProcess, INFINITE CloseHandle p.hThread CloseHandle p.hProcess compressedName = Left(expandedName, _ Len(expandedName) - 1) & "_" End Sub Public Sub expand() Dim openStruct As OFSTRUCT hSource& = LZOpenFile(compressedName, openStruct, OF_READ) ' Note: Do not use expName$ you will get a access violation. ' take care to pre-allocate space. hDestination& = LZOpenFile(expandedName, openStruct, OF_CREATE) ret& = bytesOfDest = LZCopy(hSource&, hDestination&) LZClose hDestination& LZClose hSource& End Sub Public Sub read(recNum As Long, recLen As Long, recBuf As String) Dim openStruct As OFSTRUCT hSource& = LZOpenFile(compressedName, openStruct, OF_READ) LZSeek hSource&, recLen * (recNum - 1), 0 LZRead hSource&, recBuf, recLen LZClose hSource& End Sub
The compress function is interesting because it starts a subprocess with the COMPRESS executable. This subprocess is affected by the properties associated with the COMPRESS.EXE file (especially the close_window_on_exit flag), which you can view on the
Program tab of the Properties dialog box). Figure 22.1 shows the Properties dialog box. Display this dialog box by opening the Windows Explorer program, locating the COMPRESS.EXE file in the setupkit subdirectory under the Visual Basic directory,
right-clicking on the file, and selecting the Properties menu option. Then, click on the Program tab. You will see the Close_Window_on_Exit checkbox. Make sure that it is checked so that the window will close when the compress program is finished running.
Figure 22.1. The Properties dialog box for COMPRESS.EXE.
Listing 22.7 shows the program that uses the COMPRESSION class. It uses a form with two text boxes and two command buttons. Place the text boxes one above the other; place the buttons side by side.
When the program starts, only the button labeled Create Testfile is active. Pressing it makes the program create a test file of 26 fixed-length records in a file called TESTFILE.DAT. The file is then compressed. A message box displays, allowing you time
to look at both the TEXTFILE.DAT file and the compressed version, TEXTFILE.DA_.
The next step is the deletion of the original data file; you are again prompted to check the files. After you click OK, the compressed file is expanded so that you can verify that the act of compression did not lose any data.
The final actions of the Create Testfile button are to activate the second button, deactivate itself, and read the first compressed record.
Option Explicit Private Type Record ' Define user-defined type. ID As String * 3 Name As String * 20 End Type Dim MyRecord As Record Dim recIdx As Long Dim recBuf As String * 100 Dim F As New COMPRESSION Private Sub Command1_Click() Dim idx As Long F.fileName = "testfile.dat" Open F.fileName For Random As #1 Len = Len(MyRecord) For idx = 0 To 25 MyRecord.ID = CStr(idx) + 1 MyRecord.Name = "*" & String(18, idx + Asc("A")) & "*" Put #1, , MyRecord Next idx Close #1 F.compress MsgBox "textfile.dat has been compressed...Go Look! Then click OK." Kill "testfile.dat" MsgBox "testfile.dat has been deleted...Go Look! Then click OK." F.expand MsgBox "textfile.da_ has been expanded...Go Look! Then click OK." Command1.Enabled = False Command2.Enabled = True readRec End Sub Private Sub Command2_Click() If recIdx > 26 Then recIdx = 1 readRec End Sub Private Sub Form_Load() Command1.Caption = "Create TestFile" Command2.Caption = "Next Record" Command2.Enabled = False recIdx = 1 End Sub Private Sub readRec() F.read recIdx, Len(MyRecord), recBuf MyRecord.ID = Left(recBuf, 3) MyRecord.Name = Mid(recBuf, 4) Text1.text = MyRecord.ID Text2.text = MyRecord.Name recIdx = recIdx + 1 End Sub
When you click the Next Record button, the next record is read. If the end of the records are reached, the method cycles back to the first record.
The readRec method is at the heart of the record-reading activity. It uses the read method of the COMPRESSION class to fill a buffer with the data located at record number recIdx. Then the record buffer is parsed to fill the MyRecord structure.
Visual Basic can display text only along the 0º axis, from left to right. It is sometimes useful to be able to display fonts in other orientations. For example, if text relates to several controls, you may want to display the related text
vertically.
By using Windows 95 API functions, you can rotate fonts. The class module in Listing 22.8 defines the ROTATEFONT class. Its main function, dispText, displays text at any angle.
Option Explicit Private Const OUT_DEFAULT_PRECIS = 0 Private Const OUT_STRING_PRECIS = 1 Private Const OUT_CHARACTER_PRECIS = 2 Private Const OUT_STROKE_PRECIS = 3 Private Const OUT_TT_PRECIS = 4 Private Const OUT_DEVICE_PRECIS = 5 Private Const OUT_RASTER_PRECIS = 6 Private Const OUT_TT_ONLY_PRECIS = 7 Private Const OUT_OUTLINE_PRECIS = 8 Private Const CLIP_DEFAULT_PRECIS = 0 Private Const CLIP_CHARACTER_PRECIS = 1 Private Const CLIP_STROKE_PRECIS = 2 Private Const CLIP_MASK = &HF Private Const CLIP_LH_ANGLES = 16 Private Const CLIP_TT_ALWAYS = 32 Private Const CLIP_EMBEDDED = 128 Private Const DEFAULT_QUALITY = 0 Private Const DRAFT_QUALITY = 1 Private Const PROOF_QUALITY = 2 Private Const DEFAULT_PITCH = 0 Private Const FIXED_PITCH = 1 Private Const VARIABLE_PITCH = 2 Private Const ANSI_CHARSET = 0 Private Const DEFAULT_CHARSET = 1 Private Const SYMBOL_CHARSET = 2 Private Const SHIFTJIS_CHARSET = 128 Private Const HANGEUL_CHARSET = 129 Private Const CHINESEBIG5_CHARSET = 136 Private Const OEM_CHARSET = 255 ' Font Families ' Private Const FF_DONTCARE = 0 ' Don't care or don't know. Private Const FF_ROMAN = 16 ' Variable stroke width, serifed. ' Times Roman, Century Schoolbook, etc. Private Const FF_SWISS = 32 ' Variable stroke width, sans-serifed. ' Helvetica, Swiss, etc. Private Const FF_MODERN = 48 ' Constant stroke width, serifed or sans-serifed. ' Pica, Elite, Courier, etc. Private Const FF_SCRIPT = 64 ' Cursive, etc. Private Const FF_DECORATIVE = 80 ' Old English, etc. ' Font Weights Private Const FW_DONTCARE = 0 Private Const FW_THIN = 100 Private Const FW_EXTRALIGHT = 200 Private Const FW_LIGHT = 300 Private Const FW_NORMAL = 400 Private Const FW_MEDIUM = 500 Private Const FW_SEMIBOLD = 600 Private Const FW_BOLD = 700 Private Const FW_EXTRABOLD = 800 Private Const FW_HEAVY = 900 Private Type LOGFONT lfHeight As Long lfWidth As Long lfEscapement As Long lfOrientation As Long lfWeight As Long lfItalic As Byte lfUnderline As Byte lfStrikeOut As Byte lfCharSet As Byte lfOutPrecision As Byte lfClipPrecision As Byte lfQuality As Byte lfPitchAndFamily As Byte lfFaceName As String * 32 End Type Private Declare Function CreateFontIndirect Lib "gdi32" _ Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) As Long Private Declare Function SelectObject Lib "gdi32" _ (ByVal hDC As Long, ByVal hObject As Long) As Long Private Declare Function TextOut Lib "gdi32" Alias "TextOutA" _ (ByVal hDC As Long, ByVal x As Long, ByVal y As Long, _ ByVal lpString As String, ByVal nCount As Long) As Long Private Declare Function DeleteObject Lib "gdi32" _ (ByVal hObject As Long) As Long Private font As LOGFONT Private Sub Class_Initialize() font.lfHeight = 10 font.lfWidth = 0 font.lfEscapement = 0 font.lfPitchAndFamily = FF_MODERN font.lfCharSet = ANSI_CHARSET font.lfQuality = PROOF_QUALITY font.lfWeight = FW_NORMAL font.lfFaceName = "" End Sub Public Sub setPointSize(ps As Long) font.lfHeight = ps End Sub Public Sub setAngle(angle As Long) font.lfEscapement = angle * 10 End Sub Public Sub dispText(hDC As Long, text As String, x As Long, y As Long) Dim hFont As Long Dim hOldFont As Long hFont = CreateFontIndirect(font) hOldFont = SelectObject(hDC, hFont) TextOut hDC, x, y, text, Len(text) hFont = SelectObject(hDC, hOldFont) DeleteObject hFont End Sub
Listing 22.8 has quite a few constants defined for controlling which font is used with the TextOut API function. Before looking at the listing in detail, look at the program that uses the ROTATEFONT class; see Listing 22.9. Figure 22.2 shows the results
of this program.
Figure 22.2. The output of using the ROTATEFONT class, example 1.
Private Sub Form_Click() Dim font As New ROTATEFONT font.setPointSize 36 font.setAngle 10 font.dispText Form1.hDC, "Frank and Burgers", 10, 100 font.setAngle 5 font.dispText Form1.hDC, "Frank and Burgers", 10, 100 font.setAngle -5 font.dispText Form1.hDC, "Frank and Burgers", 10, 100 font.setAngle -10 font.dispText Form1.hDC, "Frank and Burgers", 10, 100 End Sub
This first example shows that you have to do several things to display rotated text. First, you must define a variable as New ROTATEFONT. Then you must set the PointSize and Angle. Finally, you call the dispText method to print the text. Notice that you
can use negative angles as well as positive ones when specifying the axis to use.
It is important to note that the display functions are called from the Click method and not the Load method. If you place the same code in the Load method, nothing is displayed on the form because the form has not yet finished being initialized.
Example 2 in Listing 22.10 shows the effect of printing using all four points of the compass. Figure 22.3 shows the results of this small program.
Figure 22.3. The output of using the ROTATEFONT class, example 2.
Private Sub Form_Click() Dim font As New ROTATEFONT font.setPointSize 14 font.setAngle 0 font.dispText Form1.hDC, "Frank and Burgers", 200, 150 font.setAngle 90 font.dispText Form1.hDC, "Frank and Burgers", 200, 150 font.setAngle 180 font.dispText Form1.hDC, "Frank and Burgers", 200, 150 font.setAngle 270 font.dispText Form1.hDC, "Frank and Burgers", 200, 150 End Sub
Now let's go back and look briefly at Listing 22.8, where the ROTATEFONT class was defined. To use the TextOut API function, Windows must know which font it should use to display the text. You can describe a logical font using the LOGFONT structure. A
logical font can be thought of as a font description. When Windows actually needs to display the font, the best font available is used. Windows cannot choose a font to use until it knows which device will be used to display the text. The font selected for
displaying on a monitor might be different from what is used to display the same logical font on a printer. Table 22.2 describes the different members of the LOGFONT structure.
Member Name |
Description |
lfHeight |
This member specifies the height, in logical units, of the font. Windows will find the largest font that does not exceed lfHeight. |
lfWidth |
This member specifies the average width, in logical units, of characters in the font. If zero, Windows will use the aspect ratio of the device to determine the closest font match. |
lfEscapement |
This member specifies the angle, in tenths of a degree, relative to the bottom of the page. Not all devices support this ability. |
lfOrientation |
This member specifies the orientation, in tenths of a degree, of each character's base line relative to the bottom of the page. Not all devices support this ability. |
lfWeight |
The member specifies the weight of the font. Although any number from 0 to 1,000 is valid (constants starting with FW are supplied), only 400 for Normal weight and 700 for Bold is supported. Any value over 550 is displayed as bold. |
lfItalic |
This member, when set to TRUE, specifies an italicized font. |
ifUnderline |
This member, when set to TRUE, requests an underlined font. |
lfStrikeout |
This member, when set to TRUE, requests a font with a strikeout line. |
lfCharSet |
This member specifies the character set to be used for the font. ANSI_CHARSET, OEM_CHARSET, SYMBOL_CHARSET, and UNICODE_CHARSET are the currently defined values. |
lfOutPrecision |
This member specifies how closely the output must match the requested font. OUT_CHARACTER_PRECIS, OUT_DEFAULT_PRECIS, OUT_STRING_PRECIS, and OUT_STROKE_PRECIS are the defined values. |
lfClipPrecision |
This member specifies how to clip characters that display partially outside the clipping region. CLIP_CHARACTER_PRECIS, CLIP_DEFAULT_PRECIS, and CLIP_STROKE_PRECIS are the defined values. |
lfQuality |
This member specifies how carefully Windows is to be in matching the logical font to a physical font. DEFAULT_QUALITY, DRAFT_QUALITY, and PROOF_QUALITY are the defined values. |
lfPitchAndFamily |
This member specifies both the pitch and the family of the typeface. Typically, the values DEFAULT_PITCH, FIXED_PITCH, or VARIABLE_PITCH are ORed with FF_DECORATIVE, FF_DONTCARE, FF_MODERN, FF_ROMAN, FF_SCRIPT, or FF_SWISS. |
lfFaceName |
This member specifies the typeface of the font. If NULL, a default typeface is used. |
The default values of the logical font are set in the Class_Initialize function in the ROTATEFONT class module. Functions are provided to allow the programmer to change the default characteristics. This implementation of rotated text is very primitive.
No thought has been given to checking whether the device has the capability to display rotated text or to changing the orientation of text.
One of the most recent enhancements to the user interface is the ToolTip. A ToolTip is the little window that pops up when you hold the mouse cursor over an icon or menu item for more than a second or so.
To duplicate this feature in Visual Basic, you must be able to capture mouse events while the cursor is over an object. The SetCapture API function sends all mouse events to a window (specified by hWnd). It is important to remember that each Visual
Basic control is considered a window so that each control can potentially issue the SetCapture function.
The SetCapture function captures all mouse events, even those for other processes. Therefore, it is important to call the ReleaseCapture API function when the mouse moves away from your window.
The code in Listing 22.11 shows how this is done. The following line is used to determine whether the mouse has moved away from the Command1 control:
If x > Command1.Width Or x < 0 Or y > Command1.Height Or y < 0 Then
The ReleaseCapture function is also called if the Command1 control is clicked.
The TOOLTIP form consists of two command buttons, one picture box, and a timer. These can be placed anywhere on the form. The appearance property of the picture box should be set to 0 to eliminate the 3-D effect. This must be done at design time.
Option Explicit Private Declare Function SetCapture Lib "user32" _ (ByVal hwnd As Long) As Long Private Declare Function ReleaseCapture Lib "user32" () As Long Private Sub Command1_Click() Timer1.Enabled = False ReleaseCapture Picture1.Visible = False End Sub Private Sub Command1_MouseMove(Button As Integer, _ Shift As Integer, x As Single, y As Single) If x > Command1.Width Or x < 0 Or y > Command1.Height Or y < 0 Then Timer1.Enabled = False ReleaseCapture Picture1.Visible = False Else If Not Picture1.Visible Then Timer1.Enabled = True SetCapture Command1.hwnd End If End If End Sub Private Sub Form_Load() Picture1.BackColor = Form1.BackColor Picture1.Visible = False Timer1.Interval = 250 Timer1.Enabled = False End Sub Private Sub Timer1_Timer() Dim font As New ROTATEFONT Dim hlpText As String hlpText = "Help me!" Picture1.Width = Picture1.TextWidth(hlpText) + 100 Picture1.Height = Picture1.TextHeight(hlpText) + 100 Picture1.TOP = Command1.TOP + Command1.Height + 20 Picture1.Left = Command1.Left + (Command1.Width / 2) Picture1.Visible = True Picture1.Cls font.setPointSize 12 font.dispText Picture1.hDC, hlpText, 2, 2 Timer1.Enabled = False End Sub
This code makes no pretense to be elegant. Everything is hard-coded to demonstrate the steps needed to display the ToolTip. To make real use of these concepts, create a control array and have one routine handle the ToolTips. You may want to store the
help strings in a resource file or an array so that they can be easily changed as your program changes. In addition, you can make the picture box prettier by changing the font, background colors, or maybe displaying a "thought balloon" around the
text.
This section shows how to use the OpenFile, hread, hwrite, and lclose API functions to copy files. Although you can use the FileCopy statement to copy files, the routine in Listing 22.12 is better for the following reasons:
Listing 22.12 includes two functions: firstCopy and additionalCopy. They are used in the following manner:
firstCopy "vb.gid", "vb.one" additionalCopy "vb.two"
To use these routines in your own Visual Basic program, use the Insert | Module menu option to add a module to your project. Call this module HUGECOPY.BAS and then copy the code from the CD-ROM file for Listing 22.12.
When testing the routines, try copying smaller files first. If a problem develops, you will find out quicker.
' Constants with OpenFile API call. Private Const OF_WRITE = &H1 Private Const OF_READ = &H0 Private Const OF_CREATE = &H1000 ' Structure filled in by OpenFile API call. Private Type OFSTRUCT cBytes As Byte fFixedDisk As Byte nErrCode As Integer Reserved1 As Integer Reserved2 As Integer szPathName(128) As Byte End Type ' declarations for the API functions that this class uses. Private Declare Function OpenFile Lib "kernel32" _ (ByVal lpFileName As String, _ lpReOpenBuff As OFSTRUCT, _ ByVal wStyle As Long) As Long Private Declare Function hread Lib "kernel32" Alias "_hread" _ (ByVal hFile As Long, lpBuffer As Any, ByVal lBytes As Long) As Long Private Declare Function hwrite Lib "kernel32" Alias "_hwrite" _ (ByVal hFile As Long, ByVal lpBuffer As String, ByVal lBytes As Long) As Long Private Declare Function lclose Lib "kernel32" Alias "_lclose" _ (ByVal hFile As Long) As Long Private inpOFS As OFSTRUCT Private outOFS As OFSTRUCT Private myBuf As String Private size As Long Public Sub firstCopy(inp As String, out As String) Dim hInp As Long Dim hOut As Long size = FileLen(inp) myBuf = String(size, "*") hInp = OpenFile(inp, inpOFS, OF_READ) hOut = OpenFile(out, outOFS, OF_CREATE Or OF_WRITE) If (hInp <> -1 And hOut <> -1) Then hread hInp, ByVal myBuf, size hwrite hOut, ByVal myBuf, size End If lclose hOut lclose hInp End Sub Public Sub additionalCopy(out As String) Dim hOut As Long hOut = OpenFile(out, outOFS, OF_CREATE Or OF_WRITE) If (hOut <> -1) Then hwrite hOut, ByVal myBuf, size End If lclose hOut End Sub
This module is pretty simple. The only tricky points are that the size variable must be global to the module so that the additionalCopy function can see it and that the space function is used to allocate memory.
You can use the space function to read an entire database into memory. Then you can access it with the various string-manipulation functions (left, middle, right, and instr). In fact, searching a file for a phrase becomes much easier if the file is
entirely in memory.
The following sections discuss the four API functions used by the HUGECOPY code module.
The OpenFile API function can be used to open, create, or delete a file; it can also be used to test for a file's existence. First, let's look at the syntax of the function; then you will see how to control which action it performs. The syntax is as
follows:
Private Declare Function OpenFile Lib "kernel32" (ByVal lpFileName As String, _ lpReOpenBuff As OFSTRUCT, _ ByVal wStyle As Long) As Long
As you can see, the OpenFile function is located in the file KERNEL32.DLL, takes three parameters, and returns a long value. The return value is a file handle if a file was successfully opened or created. If the action to be performed was to check a
file's existence or delete a file, the return value is irrelevant unless an error occurred. The return value is HFILE_ERROR (—1) if an error has occurred.
The parameter lpFileName is the name of the file on which the function is to perform an action.
The parameter lpReOpenBuff is the address of an OFSTRUCT structure that is to be valued by the OpenFile function. This structure, shown here, has only three interesting members:
Private Type OFSTRUCT cBytes As Byte fFixedDisk As Byte nErrCode As Integer Reserved1 As Integer Reserved2 As Integer szPathName(OFS_MAXPATHNAME) As Byte End Type
The fFixedDisk member is set to nonzero if lpFileName is on a fixed disk. The szPathName member holds the full path of the file. The nErrCode member is set to the error code if the OpenFile action fails. Table 22.3 shows a list of the possible error
codes that nErrCode can be set to. Some of the error codes in Table 22.3 do not directly relate to copying with the HUGECOPY module; however it is good to see the wide range of possible errors so that you can plan other uses for the OpenFile function.
Constant Name |
Value |
Description |
ERROR_INVALID_FUNCTION |
1& |
|
ERROR_FILE_NOT_FOUND |
2& |
|
ERROR_PATH_NOT_FOUND |
3& |
|
ERROR_TOO_MANY_OPEN_FILES |
4& |
|
ERROR_ACCESS_DENIED |
5& |
|
ERROR_INVALID_HANDLE |
6& |
|
ERROR_ARENA_TRASHED |
7& |
There was a problem with the storage control blocks. |
ERROR_NOT_ENOUGH_MEMORY |
8& |
There was not enough storage space to process the action. |
ERROR_INVALID_BLOCK |
9& |
The storage control block address was invalid. |
ERROR_BAD_ENVIRONMENT |
10& |
|
ERROR_BAD_FORMAT |
11& |
An attempt was made to load a program with an incorrect format. |
ERROR_INVALID_ACCESS |
12& |
The access code was invalid. |
ERROR_INVALID_DATA |
13& |
|
ERROR_INVALID_DRIVE |
15& |
The system can't find the requested drive. |
ERROR_CURRENT_DIRECTORY |
16& |
A directory that is attached to can't be deleted. |
ERROR_NOT_SAME_DEVICE |
17& |
The system can only move a file from one directory to another on the same disk drive. You attempted to move a file to another disk drive. |
ERROR_NO_MORE_FILES |
18& |
|
ERROR_WRITE_PROTECT |
19& |
The media on which the file was to be written or created is write-protected. |
ERROR_BAD_UNIT |
20& |
The system can't find the requested device. |
ERROR_NOT_READY |
21& |
The requested device is not ready. |
ERROR_BAD_COMMAND |
22& |
The requested device does not understand the requested action. |
ERROR_CRC |
23& |
The action caused a data error. |
ERROR_BAD_LENGTH |
24& |
The requested command has the wrong length. |
ERROR_SEEK |
25& |
The requested device could not find an area on the media it was searching. |
ERROR_NOT_DOS_DISK |
26& |
The requested device could not be accessed. |
ERROR_SECTOR_NOT_FOUND |
27& |
The requested device could not find a section on the media it was searching. |
ERROR_OUT_OF_PAPER |
28& |
The printer is out of paper. |
ERROR_WRITE_FAULT |
29& |
The system could not write to the requested device. |
ERROR_READ_FAULT |
30& |
The system could not read from the requested device. |
ERROR_GEN_FAILURE |
31& |
The requested device is not functioning. |
ERROR_SHARING_VIOLATION |
32& |
The requested file is currently being used by another process. |
ERROR_LOCK_VIOLATION |
33& |
The requested file is currently locked, in whole or part, by another process. |
ERROR_WRONG_DISK |
34& |
The wrong floppy disk is in the drive. This error can occur when installing software from floppy disk. |
ERROR_SHARING_BUFFER_EXCEEDED |
36& |
The system has too many shared files open and can't open another. |
ERROR_NOT_SUPPORTED |
50& |
The system does not support the network request specified. |
ERROR_REM_NOT_LIST |
51& |
The remote computer requested is not available. |
ERROR_DUP_NAME |
52& |
A duplicate name exists on the network. |
ERROR_BAD_NETPATH |
53& |
The requested network path was not found. |
ERROR_NETWORK_BUSY |
54& |
|
ERROR_DEV_NOT_EXIST |
55& |
The requested network resource of device is no longer available. |
ERROR_TOO_MANY_CMDS |
56& |
The network BIOS command limit has been reached. |
ERROR_ADAP_HDW_ERR |
57& |
A network adapter hardware error has been detected. |
ERROR_BAD_NET_RESP |
58& |
The requested server can't perform the action. |
ERROR_UNEXP_NET_ERR |
59& |
An unexpected network error has occurred. |
ERROR_BAD_REM_ADAP |
60& |
The remote adapter is not compatible. |
ERROR_PRINTQ_FULL |
61& |
The printer queue is full. |
ERROR_NO_SPOOL_SPACE |
62& |
The spooler has run out of space on the server for the queue. |
ERROR_PRINT_CANCELLED |
63& |
The file that was waiting to be printed has been deleted. |
ERROR_NETNAME_DELETED |
64& |
The requested network name is no longer available. |
ERROR_NETWORK_ACCESS_DENIED |
65& |
|
ERROR_BAD_DEV_TYPE |
66& |
The network resource type is not correct. |
ERROR_BAD_NET_NAME |
67& |
The requested network name can't be found. |
ERROR_TOO_MANY_NAMES |
68& |
The name limit for the local network adapter card has been exceeded. |
ERROR_TOO_MANY_SESS |
69& |
The network BIOS session limit has been exceeded. |
ERROR_SHARING_PAUSED |
70& |
The remote server has been paused or is being started. |
ERROR_REQ_NOT_ACCEP |
71& |
The network request was not accepted. |
ERROR_REDIR_PAUSED |
72& |
The requested printer or device has been paused. |
ERROR_FILE_EXISTS |
80& |
|
ERROR_CANNOT_MAKE |
82& |
The requested directory or file could not be created. |
ERROR_FAIL_I24 |
83& |
A failure has occurred during an interrupt 24 call. |
ERROR_OUT_OF_STRUCTURES |
84& |
There is no storage space left in which to process this request. |
ERROR_ALREADY_ASSIGNED |
85& |
The local device is already in use. |
ERROR_INVALID_PASSWORD |
86& |
The network password was incorrect. |
ERROR_INVALID_PARAMETER |
87& |
|
ERROR_NET_WRITE_FAULT |
88& |
A write fault has occurred on the network. |
The last parameter of the OpenFile function is wStyle. It is used to tell OpenFile which actions to perform. The basic actions are OF_CREATE, OF_DELETE, OF_EXIST, OF_READ, OF_VERIFY, and OF_WRITE (see Table 22.4).
You can also use _ to modify the basic actions. For example, you can use OF_PROMPT to tell Visual Basic to prompt the user for a filename if the requested file is not found.
Constant Name |
Value |
Description |
OF_READ |
&H0 |
This flag opens the file for read access only. |
OF_WRITE |
&H1 |
This flag opens the file for write access only. |
OF_READWRITE |
&H2 |
This flag opens the file for read and write access. |
OF_SHARE_COMPAT |
&H0 |
This flag opens the file in compatibility mode, which allows any program on the same computer to open the file any number of times. |
OF_SHARE_EXCLUSIVE |
&H10 |
This flag opens the file and prevents other programs from either reading or writing the file. |
OF_SHARE_DENY_WRITE |
&H20 |
This flag opens the file and prevents other programs from writing to it. |
OF_SHARE_DENY_READ |
&H30 |
This flag opens the file and prevents other programs from reading from it. |
OF_SHARE_DENY_NONE |
&H40 |
This flag opens the file without denying other programs read or write access to the file. |
OF_PARSE |
&H100 |
This flag causes the system to fill the OFSTRUCT buffer with information. |
OF_DELETE |
&H200 |
This flag causes the file to be deleted. |
OF_VERIFY |
&H400 |
This flag causes the system to compare the date and time in the OFSTRUCT buffer with that of the file. The value HFILE_ERROR (—1) is returned if the time and date are different. |
OF_CANCEL |
&H800 |
This flag adds a Cancel button to the dialog box OF_PROMPT uses. |
OF_CREATE |
&H1000 |
This flag creates a new file. If the file already exists, it is overwritten. |
OF_PROMPT |
&H2000 |
This flag causes the system to display a dialog box if the named file does not exist. The dialog box asks the user to insert into drive A a disk that contains the file. |
OF_EXIST |
&H4000 |
This flag opens the file and then closes it to see whether the file exists. It does not change the last-modified date of the file. |
OF_REOPEN |
&H8000 |
This flag opens the file using the information in the OFSTRUCT buffer. |
The system looks for the file using the following search criteria:
The hread API function is used to read data from an open file into a buffer in memory. It can handle blocks of data greater than 64K. The syntax is as follows:
Private Declare Function hread Lib "kernel32" Alias "_hread" _ (ByVal hFile As Long, lpBuffer As Any, ByVal lBytes As Long) As Long
The hread function is located in the KERNEL32.DLL file, takes three parameters, and returns a long value. The return value is the number of bytes read or HFILE_ERROR (—1).
The hFile parameter is the file handle of an open file. In the example in Listing 22.12, the handle was the return value of the OpenFile function.
The lpBuffer parameter is the location of a buffer to receive the data from the file. Make sure that the buffer is initialized before this function is called.
The lBytes parameter is the number of bytes of data to read. If the return value is less that lBytes, the end of the file was reached before all of the requested data was read.
The hread API function is used to read data from an open file into a buffer in memory. It can handle blocks of data greater than 64K. The syntax is as follows:
Private Declare Function hwrite Lib "kernel32" Alias "_hwrite" _ (ByVal hFile As Long, ByVal lpBuffer As String, ByVal lBytes As Long) As Long
The hwrite function is located in the KERNEL32.DLL file, takes three parameters, and returns a long value. The return value is the number of bytes written or HFILE_ERROR (—1).
The hFile parameter is the file handle of an open file. In the example in Listing 22.12, the handle was the return value of the OpenFile function.
The lpBuffer parameter is the location of the buffer whose contents are to be written to the file.
The lBytes parameter is the number of bytes of data to write.
The lclose API function is used to close an open file. Its syntax is as follows:
Private Declare Function lclose Lib "kernel32" Alias "_lclose" _ (ByVal hFile As Long) As Long
The lclose function is located in the KERNEL32.DLL file, takes one argument, and returns a long value. The return value is zero for successful completion or HFILE_ERROR (—1) if the system could not close the file.
This chapter covered many different types of API functions. And yet, in reality, it barely scratched the surface of the functionality available to you with the Windows API library.
One piece of advice: before looking for a solution using an API function, either look for a way that Visual Basic can perform the task (you may have overlooked something in the manuals) or see whether an existing OCX can perform the task for you.
Spending time debugging API calls can be frustrating and takes away time from your main programming task.